package yang.itcode.service.impl;

import cn.hutool.json.JSONObject;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yang.itcode.exception.BusinessException;
import yang.itcode.mapper.CostMapper;
import yang.itcode.mapper.InventoryDetailMapper;
import yang.itcode.model.pojo.Cost;
import yang.itcode.model.pojo.InventoryDetail;
import yang.itcode.service.CostService;
import yang.itcode.utils.ThreadUtil;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import static yang.itcode.constant.ErrorConstant.*;
import static yang.itcode.constant.OptionConstant.*;

@Service
public class CostServiceImpl implements CostService {

    @Autowired
    private CostMapper costMapper;
    @Autowired
    private InventoryDetailMapper inventoryDetailMapper;

    @Override
    public JSONObject getCostChangeList(JSONObject obj) {
        if ("year".equals(obj.getStr("mode"))){
            LocalDate startDate = obj.get("startDate", LocalDate.class);
            LocalDate endDate = obj.get("endDate", LocalDate.class);
            JSONObject yearRange = obj.getJSONObject("yearRange");
            int startYear = yearRange.getInt("start");
            int endYear = yearRange.getInt("end");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            List<JSONObject> list = new ArrayList<>();
            JSONObject condition = new JSONObject();
            condition.set("productId", obj.getInt("productId"));
            condition.set("startDate", startDate);
            condition.set("endDate", endDate);
            condition.set("status", 1);
            condition.set("orderBy", "create_time");
            condition.set("sortOrder", "asc");
            List<Cost> costs = costMapper.selectByCondition(condition);
            for (Cost detail : costs) {
                JSONObject item = new JSONObject();
                item.set("time", detail.getCreateTime().format(formatter));
                item.set("cost", detail.getCurrentAvgCost());
                list.add(item);
            }
            obj.set("list", list);
            return obj;
        } else if ("month".equals(obj.getStr("mode"))){
            LocalDate startDate = obj.get("startDate", LocalDate.class);
            LocalDate endDate = obj.get("endDate", LocalDate.class);
            JSONObject monthRange = obj.getJSONObject("monthRange");
            // 解析范围的YYYY-MM格式字符串
            String startMonthStr = monthRange.getStr("start");
            String endMonthStr = monthRange.getStr("end");
            String[] startParts = startMonthStr.split("-");
            String[] endParts = endMonthStr.split("-");
            int startYear = Integer.parseInt(startParts[0]);
            int startMonth = Integer.parseInt(startParts[1]);
            int endYear = Integer.parseInt(endParts[0]);
            int endMonth = Integer.parseInt(endParts[1]);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            List<JSONObject> list = new ArrayList<>();
            JSONObject condition = new JSONObject();
            condition.set("productId", obj.getInt("productId"));
            condition.set("startDate", startDate);
            condition.set("endDate", endDate);
            condition.set("status", 1);
            condition.set("orderBy", "create_time");
            condition.set("sortOrder", "asc");
            List<Cost> costs = costMapper.selectByCondition(condition);
            for (Cost detail : costs) {
                JSONObject item = new JSONObject();
                item.set("time", detail.getCreateTime().format(formatter));
                item.set("cost", detail.getCurrentAvgCost());
                list.add(item);
            }
            obj.set("list", list);
            return obj;
        } else if ("day".equals(obj.getStr("mode"))){
            LocalDate startDate = obj.get("startDate", LocalDate.class);
            LocalDate endDate = obj.get("endDate", LocalDate.class);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            List<JSONObject> list = new ArrayList<>();
            JSONObject condition = new JSONObject();
            condition.set("productId", obj.getInt("productId"));
            condition.set("startDate", startDate);
            condition.set("endDate", endDate);
            condition.set("status", 1);
            condition.set("orderBy", "create_time");
            condition.set("sortOrder", "asc");
            List<Cost> costs = costMapper.selectByCondition(condition);
            for (Cost detail : costs) {
                JSONObject item = new JSONObject();
                item.set("time", detail.getCreateTime().format(formatter));
                item.set("cost", detail.getCurrentAvgCost());
                list.add(item);
            }
            obj.set("list", list);
            return obj;
        }
        return null;
    }

    @Override
    @Transactional
    public Boolean adjustCost(JSONObject obj) {
        Integer userId = ThreadUtil.getCurrentId();
        Integer productId = obj.getInt("productId");
        BigDecimal originalAvgCost = obj.getBigDecimal("originalAvgCost");
        BigDecimal adjustCost = obj.getBigDecimal("adjustCost");
        BigDecimal currentAvgCost = obj.getBigDecimal("currentAvgCost");
        BigDecimal originalTotal = obj.getBigDecimal("originalTotal");
        BigDecimal newTotal = obj.getBigDecimal("newTotal");
        BigDecimal inventory = obj.getBigDecimal("inventory");
        String note = obj.getStr("note");
        // 校验必填参数
        if (productId == null || adjustCost == null) {
            throw new BusinessException(COST_PARAM_EXCEPTION_CODE, COST_PARAM_EXCEPTION_MESSAGE);
        }
        // 新总成本不得小于0
        if (newTotal.compareTo(BigDecimal.ZERO) < 0) {
            throw new BusinessException(COST_PARAM_EXCEPTION_CODE, COST_PARAM_EXCEPTION_MESSAGE);
        }
        // 成本记录
        Cost cost = new Cost();
        cost.setProductId(productId);
        cost.setDate(LocalDate.now());
        cost.setOperationType(COST_OPERATION_ADJUST);
        cost.setOriginalAvgCost(originalAvgCost);
        cost.setAdjustCost(adjustCost);
        cost.setCurrentAvgCost(currentAvgCost);
        cost.setInventory(inventory);
        cost.setNote(note);
        cost.setCreateUserId(userId);
        cost.setUpdateUserId(userId);
        int insertCostResult = costMapper.insert(cost);
        if (insertCostResult < 1) {
            throw new BusinessException(COST_ADJUST_EXCEPTION_CODE, COST_ADJUST_EXCEPTION_MESSAGE);
        }
        // 查询最新记录
        JSONObject condition = new JSONObject();
        condition.set("productId", productId);
        condition.set("status", 1);
        condition.set("orderBy", "create_time");
        condition.set("sortOrder", "desc");
        PageHelper.startPage(1,1);
        List<Cost> costs = costMapper.selectByCondition(condition);
        if (costs.size() == 0) {
            throw new BusinessException(COST_ADJUST_EXCEPTION_CODE, COST_ADJUST_EXCEPTION_MESSAGE);
        }
        Cost latestCost = costs.get(0);
        // 更新库存明细的成本
        InventoryDetail inventoryDetail = new InventoryDetail();
        inventoryDetail.setProductId(productId);
        inventoryDetail.setOperationType(INVENTORY_OPTION_COST_ADJUST);
        inventoryDetail.setQuantity(BigDecimal.ZERO);
        inventoryDetail.setCurrentAvgCost(currentAvgCost);
        inventoryDetail.setBalanceQuantity(inventory);
        inventoryDetail.setBalanceValue(newTotal);
        inventoryDetail.setDate(LocalDate.now());
        inventoryDetail.setNote("成本调整记录变化，调整单Id：" + latestCost.getId());
        inventoryDetail.setRelatedId(latestCost.getId());
        inventoryDetail.setCreateUserId(userId);
        inventoryDetail.setUpdateUserId(userId);
        int insertInventoryDetailResult = inventoryDetailMapper.insert(inventoryDetail);
        if (insertInventoryDetailResult < 1) {
            throw new BusinessException(COST_ADJUST_EXCEPTION_CODE, COST_ADJUST_EXCEPTION_MESSAGE);
        }
        return true;
    }
}
